home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / makemdi2.zip / SHEET.C < prev    next >
C/C++ Source or Header  |  1992-11-25  |  15KB  |  483 lines

  1. #define _SHEET_C
  2. //----------------------------------------------------------------- 
  3. // SHEET.C - Sheet window management. 
  4. // 
  5. // MAKEMDI adaptation of Windows 3.1 SDK MAKEAPP system. 
  6. // 
  7. // MDI application design based on Chapter 7 of     
  8. // "Windows 3: A Developer's Guide" by Jeffrey Richter. 
  9. // 
  10. // Adaptation developed with permission of the author by  
  11. // John F. Holliday, Technisoft Corporation 
  12. // Telephone: (515) 472-9803, CompuServe: 71271,634 
  13. //
  14. // [DMM]    25-Nov-1992: Fixed crashing on exit
  15. //            Also tabified file to tabsize of 4
  16. //
  17. //            David M. Miller, Business Visions, Inc.
  18. //            Telephone: (212) 747-6118
  19. //            CompuServe: 72676,327
  20. //            internet: dmiller@hera.sbi.com
  21. //----------------------------------------------------------------- 
  22. #include "makemdi.h"
  23.  
  24. BOOL Sheet_Initialize(APP * papp)
  25. //----------------------------------------------------------------- 
  26. // Initialize all MDI child window classes. 
  27. //----------------------------------------------------------------- 
  28. {
  29.     WNDCLASS        cls;
  30.  
  31.     cls.hCursor = LoadCursor(NULL, IDC_ARROW);
  32.     cls.hIcon = NULL;
  33.     cls.lpszMenuName = NULL;
  34.     cls.hInstance = papp->hinst;
  35.     cls.lpszClassName = CLASS_SHEET;
  36.     cls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  37.     cls.lpfnWndProc = Sheet_WndProc;
  38.     cls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  39.     cls.cbWndExtra = sizeof(SHEET*);
  40.     cls.cbClsExtra = 0;
  41.  
  42.     if (!RegisterClass(&cls))
  43.         return FALSE;
  44.  
  45.     return TRUE;
  46. }
  47.  
  48. void Sheet_Terminate(APP * papp)
  49. {
  50. }
  51.  
  52. LRESULT CALLBACK _export Sheet_WndProc(HWND hWnd,
  53.                                        UINT msg,
  54.                                        WPARAM wParam,
  55.                                        LPARAM lParam)
  56. {
  57.     SHEET *psheet = Sheet_GetPtr(hWnd);
  58.  
  59.     if (psheet == NULL) {
  60.         if (msg == WM_NCCREATE) {
  61.             psheet = (SHEET *) LocalAlloc(
  62.                                    LMEM_FIXED | LMEM_ZEROINIT, sizeof(SHEET));
  63.  
  64.             if (psheet == NULL)
  65.                 return 0L;
  66.  
  67.             psheet->hWnd = hWnd;
  68.             Sheet_SetPtr(hWnd, psheet);
  69.         }
  70.         else {
  71.             return Sheet_DefProc(hWnd, msg, wParam, lParam);
  72.         }
  73.     }
  74.  
  75.  
  76.     if (msg == WM_NCDESTROY) {
  77.         // DWORD result = HANDLE_MSG(hWnd, WM_NCDESTROY, Sheet_OnNCDestroy); 
  78.  
  79.         if (psheet->hMenu != NULL)
  80.             DestroyMenu(psheet->hMenu);
  81.  
  82.         LocalFree((HLOCAL) OFFSETOF(psheet));
  83.         psheet = NULL;
  84.         Sheet_SetPtr(hWnd, NULL);
  85.  
  86.         // return result; 
  87.     }
  88.  
  89.  
  90.     switch (msg) {
  91.         HANDLE_MSG(psheet, WM_CREATE, Sheet_OnCreate);
  92.         HANDLE_MSG(psheet, WM_MDIACTIVATE, Sheet_OnMdiActivate);
  93.         HANDLE_MSG(psheet, WM_MOUSEACTIVATE, Sheet_OnMouseActivate);
  94.         HANDLE_MSG(psheet, WM_ENTERIDLE, Sheet_OnEnterIdle);
  95.         HANDLE_MSG(psheet, WM_MENUSELECT, Sheet_OnMenuSelect);
  96.         HANDLE_MSG(psheet, WM_SETCURSOR, Sheet_OnSetCursor);
  97.         HANDLE_MSG(psheet, WM_LBUTTONDOWN, Sheet_OnLButtonDown);
  98.         HANDLE_MSG(psheet, WM_CLOSE, Sheet_OnClose);
  99.         HANDLE_MSG(psheet, WM_DESTROY, Sheet_OnDestroy);
  100.         HANDLE_MSG(psheet, WM_PAINT, Sheet_OnPaint);
  101.         HANDLE_MSG(psheet, WM_ERASEBKGND, Sheet_OnEraseBkgnd);
  102.         HANDLE_MSG(psheet, WM_QUERYENDSESSION, Sheet_OnQueryEndSession);
  103.         HANDLE_MSG(psheet, WM_ENDSESSION, Sheet_OnEndSession);
  104.         HANDLE_MSG(psheet, WM_COMMAND, Sheet_OnCommand);
  105.  
  106.         // Application messages. 
  107.  
  108.         HANDLE_MSG(psheet, AC_PAINTSTATBAR, Sheet_OnPaintStatBar);
  109.         HANDLE_MSG(psheet, AW_PAINTMENUHELP, Sheet_OnPaintMenuHelp);
  110.  
  111.     default:
  112.         return Sheet_DefProc(hWnd, msg, wParam, lParam);
  113.     }
  114. }
  115.  
  116. typedef struct {
  117.     LPCSTR            lpszText;
  118.     COLORREF        clrText;
  119. }
  120. SHEET_INIT;
  121.  
  122. HWND Sheet_CreateWindow(HWND hWndParent, int x, int y, int cx, int cy, BOOL fVisible, COLORREF clrText, LPCSTR lpszText)
  123. {
  124.     SHEET_INIT        init;
  125.  
  126.     init.lpszText = lpszText;
  127.     init.clrText = clrText;
  128.  
  129.     return CreateWindowEx(
  130.                              0L,        // extendedStyle 
  131.                              CLASS_SHEET,        // class name 
  132.                              NULL,        // text 
  133.                              (fVisible ? (WS_CHILD | WS_VISIBLE) : WS_CHILD),
  134.                              x, y, cx, cy,        // x, y, cx, cy 
  135.                              hWndParent,// hWndParent 
  136.                              NULL,        // hmenu 
  137.                              g_app.hinst,        // hInstance 
  138.                              &init);    // lpCreateParams 
  139. }
  140.  
  141. BOOL Sheet_OnCreate(SHEET * psheet, CREATESTRUCT FAR * lpCreateStruct)
  142. {
  143.     SHEET_INIT FAR *pinit = (SHEET_INIT FAR *) lpCreateStruct->lpCreateParams;
  144.  
  145.     psheet->lpszText = pinit->lpszText;
  146.     psheet->clrText = pinit->clrText;
  147.  
  148.     // If this window is first instance created of this class. 
  149.  
  150.     if (psheet->hMenu == NULL) {
  151.         // Initialize the menu and accelerator handles for this class. 
  152.  
  153.         psheet->hMenu = LoadMenu(g_app.hinst, MAKEINTRESOURCE(IDR_SHEETMENU));
  154.         psheet->hAccelTable = LoadAccelerators(g_app.hinst, MAKEINTRESOURCE(IDR_SHEETACCEL));
  155.     }
  156.  
  157.     return TRUE;
  158. }
  159.  
  160. void Sheet_OnMdiActivate(SHEET * psheet, BOOL fBeingActivated, HWND hWndChild, HWND hWndPrevChild)
  161. {
  162.     if (fBeingActivated) {
  163.         // Child is being activated. 
  164.  
  165.         psheet->hWndPrevChild = hWndPrevChild;
  166.  
  167.         // If this child is being activated and no other child exists, 
  168.         // pretend that this child was the last activated child. 
  169.  
  170.         if (psheet->hWndPrevChild == NULL)
  171.             psheet->hWndPrevChild = psheet->hWnd;
  172.  
  173.         // Set the menu bar and the accelerators to the appropriate ones 
  174.         // for this window class. 
  175.  
  176.         Frame_ChangeMDIMenu(
  177.                                GETFRAME(psheet->hWnd),
  178.                                GetParent(psheet->hWnd),
  179.                                psheet->hMenu,
  180.                                CMD_WINDOWTILEVERT);
  181.  
  182.         g_app.hAccelTable = psheet->hAccelTable;
  183.  
  184.         // For the Status bar at the bottom of the Frame window to be  
  185.         // updated for this child's information. 
  186.  
  187.         InvalidateRect(GETFRAME(psheet->hWnd), NULL, TRUE);
  188.     }
  189.     else {
  190.         // Child is being deactivated. 
  191.         // Reset the previous child so WM_MOUSEACTIVATE will work Ok. 
  192.  
  193.         psheet->hWndPrevChild = NULL;
  194.     }
  195. }
  196.  
  197. int Sheet_OnMouseActivate(SHEET * psheet, HWND hWndTopLevel, UINT codeHitTest, UINT msg)
  198. //----------------------------------------------------------------- 
  199. // User clicked the mouse of the Child window. 
  200. // If the mouse is clicked in the window's client area and    
  201. // the previously active child was NOT this child, the 
  202. // mouse message should be eaten. 
  203. //----------------------------------------------------------------- 
  204. {
  205.     if ((codeHitTest == HTCLIENT) &&
  206.             (psheet->hWnd != psheet->hWndPrevChild))
  207.         return MA_ACTIVATEANDEAT;
  208.  
  209.     return MA_ACTIVATE;
  210. }
  211.  
  212. void Sheet_OnEnterIdle(SHEET * psheet, UINT source, HWND hWndSource)
  213. //----------------------------------------------------------------- 
  214. // User stopped moving around in the help system, make the Frame 
  215. // believe that it received this message directly. 
  216. //----------------------------------------------------------------- 
  217. {
  218.     FORWARD_WM_ENTERIDLE(GETFRAME(psheet->hWnd), source, hWndSource, SendMessage);
  219. }
  220.  
  221. void Sheet_OnMenuSelect(SHEET * psheet, HMENU hMenu, int item, HMENU hMenuPopup, UINT flags)
  222. //----------------------------------------------------------------- 
  223. // Normally, only MDI Child system menu options could appear 
  224. // in this message.     But the Frame window forces WM_MENUSELECT 
  225. // messages to appear here whenever a menu selection occurs. 
  226. //----------------------------------------------------------------- 
  227. {
  228.     WORD            wTemp;
  229.     HMENU            hMenuFrame;
  230.  
  231.     if (flags == -1 && (hMenu == (HMENU) 0)) {
  232.         // User has stopped using the menu system.    Notify Frame window 
  233.         // so that the status bar will be invalidated. 
  234.  
  235.         SendMessage(GETFRAME(psheet->hWnd), FW_SETMENUHELP, 0, 0);
  236.         return;
  237.     }
  238.  
  239.     switch (flags & (MF_POPUP | MF_SYSMENU)) {
  240.     case 0:
  241.         // Item is a menu item ID NOT on the Child's system menu. 
  242.         // If item is any of the MDI Children listed in the     
  243.         // "Window" menu, display the same help text. 
  244.  
  245.         if ((item > CMD_WINDOWCHILD) && (item <= CMD_WINDOWCHILD + 9))
  246.             item = CMD_WINDOWCHILD;
  247.  
  248.         wTemp = IDS_SHEETMENUID + item;
  249.         break;
  250.  
  251.     case MF_POPUP:
  252.         // Calculate the index of the top-level menu. 
  253.  
  254.         hMenuFrame = GetMenu(GETFRAME(psheet->hWnd));
  255.         wTemp = GetMenuItemCount(hMenuFrame);
  256.  
  257.         while (wTemp--)
  258.             if (GetSubMenu(hMenuFrame, wTemp) == hMenuPopup)
  259.                 break;
  260.  
  261.         wTemp += IDS_SHEETPOPUPID;
  262.  
  263.         if (!IsZoomed(psheet->hWnd))
  264.             wTemp++;
  265.         break;
  266.  
  267.     case MF_SYSMENU:
  268.         // Item is menu item ID from MDI Child's system menu. 
  269.  
  270.         wTemp = IDS_SHEETMENUID + ((item & 0x0FFF) >> 4);
  271.         break;
  272.  
  273.     case MF_POPUP | MF_SYSMENU:
  274.         // Item is handle to MDI Child's sys menu. 
  275.  
  276.         wTemp = IDS_SHEETPOPUPID;
  277.         break;
  278.     }
  279.  
  280.     // Tell the Frame that this window should display the help 
  281.     // text and the identifier for the help text. 
  282.  
  283.     SendMessage(GETFRAME(psheet->hWnd), FW_SETMENUHELP,
  284.                 (WPARAM) psheet->hWnd, (LPARAM) wTemp);
  285. }
  286.  
  287. BOOL Sheet_OnSetCursor(SHEET * psheet, HWND hWndCursor, UINT codeHitTest, UINT msg)
  288. //----------------------------------------------------------------- 
  289. // After an MDI Child becomes active, set the previously active 
  290. // child to this window so that mouse messages will NOT be eaten. 
  291. //----------------------------------------------------------------- 
  292. {
  293.     psheet->hWndPrevChild = psheet->hWnd;
  294.     return FORWARD_WM_SETCURSOR(psheet->hWnd, hWndCursor, codeHitTest, msg, Sheet_DefProc);
  295. }
  296.  
  297. void Sheet_OnLButtonDown(SHEET * psheet, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  298. //----------------------------------------------------------------- 
  299. // Just to let you know when the WM_LBUTTONDOWN message is received. 
  300. //----------------------------------------------------------------- 
  301. {
  302.     MessageBox(psheet->hWnd, "WM_LBUTTONDOWN", "Sheet", MB_OK);
  303. }
  304.  
  305. void Sheet_OnClose(SHEET * psheet)
  306. //----------------------------------------------------------------- 
  307. // Make sure that it is OK to close this child window. 
  308. //----------------------------------------------------------------- 
  309. {
  310.     if ((BOOL) SendMessage(psheet->hWnd, WM_QUERYENDSESSION, 0, 0)) {
  311.         SendMessage(psheet->hWnd, WM_ENDSESSION, TRUE, 0);
  312.         FORWARD_WM_CLOSE(psheet->hWnd, Sheet_DefProc);
  313.     }
  314. }
  315.  
  316. void Sheet_OnDestroy(SHEET * psheet)
  317. //----------------------------------------------------------------- 
  318. // Notify the Frame window that a child has been destroyed after  
  319. // the child is actually destroyed.     (That's why we use 
  320. // PostMessage instead of SendMessage here). 
  321. //----------------------------------------------------------------- 
  322. {
  323.     PostMessage(GETFRAME(psheet->hWnd), FW_MDICHILDDESTROY, (WPARAM) psheet->hWnd, 0);
  324.     FORWARD_WM_DESTROY(psheet->hWnd, Sheet_DefProc);
  325. }
  326.  
  327. void Sheet_OnPaint(SHEET * psheet)
  328. //----------------------------------------------------------------- 
  329. //----------------------------------------------------------------- 
  330. {
  331.     PAINTSTRUCT        ps;
  332.     HDC                hdc;
  333.     RECT            rc;
  334.  
  335.     hdc = BeginPaint(psheet->hWnd, &ps);
  336.  
  337.     GetClientRect(psheet->hWnd, &rc);
  338.     FillRect(hdc, &rc, GetStockBrush(WHITE_BRUSH));
  339.     InflateRect(&rc, -4, -4);
  340.     FrameRect(hdc, &rc, GetStockBrush(BLACK_BRUSH));
  341.  
  342.     if (psheet->lpszText) {
  343.         int                cch = lstrlen(psheet->lpszText);
  344.         int                x;
  345.         int                y;
  346.         SIZE            size;
  347.  
  348.         GetTextExtentPoint(hdc, psheet->lpszText, cch, &size);
  349.  
  350.         x = rc.left + (rc.right - rc.left - size.cx) / 2;
  351.         y = rc.top + (rc.bottom - rc.top - size.cy) / 2;
  352.  
  353.         SetTextColor(hdc, psheet->clrText);
  354.         TextOut(hdc, x, y, psheet->lpszText, cch);
  355.     }
  356.  
  357.     EndPaint(psheet->hWnd, &ps);
  358. }
  359.  
  360. BOOL Sheet_OnEraseBkgnd(SHEET * psheet, HDC hdc)
  361. //----------------------------------------------------------------- 
  362. // Let DefWindowProc erase the background 
  363. //----------------------------------------------------------------- 
  364. {
  365.     return FORWARD_WM_ERASEBKGND(psheet->hWnd, hdc, DefWindowProc);
  366. }
  367.  
  368. BOOL Sheet_OnQueryEndSession(SHEET * psheet)
  369. //----------------------------------------------------------------- 
  370. //----------------------------------------------------------------- 
  371. {
  372.     WORD            wTemp;
  373.     BOOL            fOkToQuit = FALSE;
  374.  
  375.     // Prompt user whether to save changes to this document. 
  376.     // Usually, a dirty flag (stored in the window's extra bytes 
  377.     // is used to determine if it is necessary to ask this question). 
  378.  
  379.     // Construct string including the document's name. 
  380.  
  381.     lstrcpy(g_app.szBuf, "Save changes to ");
  382.     wTemp = lstrlen(g_app.szBuf);
  383.     GetWindowText(psheet->hWnd, g_app.szBuf + wTemp,
  384.                   sizeof(g_app.szBuf) - wTemp);
  385.     lstrcat(g_app.szBuf, "?");
  386.  
  387.     // Display message box to user.     The message box should     
  388.     // be system modal if the entire Windows session is being  
  389.     // terminated. (wParam is FALSE). 
  390.  
  391.     switch (
  392.                MessageBox(
  393.                              psheet->hWnd,
  394.                              g_app.szBuf,
  395.                              g_app.szName,
  396.                              MB_ICONQUESTION | MB_YESNOCANCEL |
  397.                              MB_APPLMODAL)) {
  398.     case IDYES:
  399.         // Save the document and it's OK to quit. 
  400.         fOkToQuit = TRUE;
  401.         break;
  402.  
  403.     case IDNO:
  404.         // Don't save the document and it's OK to quit. 
  405.         fOkToQuit = TRUE;
  406.         break;
  407.     }
  408.  
  409.     return fOkToQuit;
  410. }
  411.  
  412. void Sheet_OnEndSession(SHEET * psheet, BOOL fEnding)
  413. //----------------------------------------------------------------- 
  414. // Do any last minute cleanup during this message. 
  415. //----------------------------------------------------------------- 
  416. {
  417. }
  418.  
  419. void Sheet_OnCommand(SHEET * psheet, int id, HWND hWndCtl, UINT codeNotify)
  420. //----------------------------------------------------------------- 
  421. // Any menu options NOT processed by the Frame are passed to the 
  422. // active child. 
  423. //----------------------------------------------------------------- 
  424. {
  425.     MessageBox(psheet->hWnd, "Option not implemented.", g_app.szName, MB_OK);
  426. }
  427.  
  428. void Sheet_OnPaintStatBar(SHEET * psheet, HDC hdc, LPPAINTSTRUCT psStatus)
  429. //----------------------------------------------------------------- 
  430. // Message sent by the Frame window when the status bar needs to  
  431. // be repainted. 
  432. //----------------------------------------------------------------- 
  433. {
  434.     // Construct status bar string for display. 
  435.  
  436.     LoadString(g_app.hinst, IDS_SHEETSTATUSBAR, g_app.szBuf, sizeof(g_app.szBuf));
  437.  
  438.     // Draw the horizontal dividing line separating the Status bar 
  439.     // from the MDICLIENT window. 
  440.  
  441.     psStatus->rcPaint.top += (int)
  442.             SendMessage(GETFRAME(psheet->hWnd), FW_DRAWSTATUSDIVIDE, 0,
  443.                         (LPARAM) psStatus);
  444.  
  445.     // Paint the text in the status bar. 
  446.  
  447.     TextOut(hdc, 0, psStatus->rcPaint.top, g_app.szBuf, lstrlen(g_app.szBuf));
  448. }
  449.  
  450. void Sheet_OnPaintMenuHelp(SHEET * psheet, LPPAINTSTRUCT psStatus)
  451. //----------------------------------------------------------------- 
  452. // Message sent from Frame window to notify child that it should 
  453. // paint the status bar text for the last highlighted menu item. 
  454. // lParam = LPPAINTSTRUCT of Frame's status bar. 
  455. //----------------------------------------------------------------- 
  456. {
  457.     LRESULT            lResult;
  458.  
  459.     // Ask the Frame window what the last selected menu ID was. 
  460.     // This value was sent to the frame by this window during the  
  461.     // processing for the WM_MENUSELECT message. 
  462.  
  463.     lResult = SendMessage(GETFRAME(psheet->hWnd), FW_GETMENUHELP, 0, 0);
  464.  
  465.     // Draw the horizontal dividing line separating the Status bar 
  466.     // from the MDICLIENT window. 
  467.  
  468.     psStatus->rcPaint.top += (int)
  469.             SendMessage(GETFRAME(psheet->hWnd), FW_DRAWSTATUSDIVIDE, 0,
  470.                         (LPARAM) psStatus);
  471.  
  472.     // Construct the string that is to be displayed. 
  473.  
  474.     LoadString(g_app.hinst, LOWORD(lResult), g_app.szFmt, sizeof(g_app.szFmt));
  475.     GetWindowText(psheet->hWnd, g_app.szCap, sizeof(g_app.szCap));
  476.     wsprintf(g_app.szBuf, g_app.szFmt, (LPSTR) g_app.szCap);
  477.  
  478.     // Paint the menu help text in the status bar. 
  479.  
  480.     TextOut(psStatus->hdc,
  481.             0, psStatus->rcPaint.top, g_app.szBuf, lstrlen(g_app.szBuf));
  482. }
  483.